/**
 * Convert H.264 AnnexB format to AVCC format
 * @param annexBData AnnexB format data buffer
 * @returns Array of AVCC format NALU data blocks
 */
export function convertAnnexBToAvcc(annexBData: Uint8Array): Uint8Array[] {
    const naluArray: Uint8Array[] = [];
    let i = 0;
    
    while (i < annexBData.length) {
        let startCodeLength = 0;
        
        // Check for 4-byte start code: 0x00000001
        if (i + 3 < annexBData.length &&
            annexBData[i] === 0x00 &&
            annexBData[i + 1] === 0x00 &&
            annexBData[i + 2] === 0x00 &&
            annexBData[i + 3] === 0x01) {
            startCodeLength = 4;
        }
        // Check for 3-byte start code: 0x000001
        else if (i + 2 < annexBData.length &&
            annexBData[i] === 0x00 &&
            annexBData[i + 1] === 0x00 &&
            annexBData[i + 2] === 0x01) {
            startCodeLength = 3;
        }
        
        if (startCodeLength > 0) {
            // Skip the start code
            i += startCodeLength;
            
            // Find the position of next start code
            let nextStartPos = annexBData.length;
            for (let j = i; j < annexBData.length; j++) {
                // Check for 4-byte start code
                if (j + 3 < annexBData.length &&
                    annexBData[j] === 0x00 &&
                    annexBData[j + 1] === 0x00 &&
                    annexBData[j + 2] === 0x00 &&
                    annexBData[j + 3] === 0x01) {
                    nextStartPos = j;
                    break;
                }
                // Check for 3-byte start code
                if (j + 2 < annexBData.length &&
                    annexBData[j] === 0x00 &&
                    annexBData[j + 1] === 0x00 &&
                    annexBData[j + 2] === 0x01) {
                    nextStartPos = j;
                    break;
                }
            }
            
            // Calculate NALU length
            const naluLength = nextStartPos - i;
            
            if (naluLength > 0) {
                // Create AVCC format NALU (4-byte length prefix + NALU data)
                const avccNalu = new Uint8Array(4 + naluLength);
                
                // Write NALU length in big-endian format
                avccNalu[0] = (naluLength >> 24) & 0xFF;
                avccNalu[1] = (naluLength >> 16) & 0xFF;
                avccNalu[2] = (naluLength >> 8) & 0xFF;
                avccNalu[3] = naluLength & 0xFF;
                
                // Copy NALU data
                avccNalu.set(annexBData.subarray(i, nextStartPos), 4);
                
                naluArray.push(avccNalu);
            }
            
            i = nextStartPos;
        } else {
            i++;
        }
    }
    
    return naluArray;
}

/**
 * Generate H.264 AVCC Configuration Record (avcC box / sequence header)
 * @param sps Sequence Parameter Set data
 * @param pps Picture Parameter Set data
 * @returns AVCC configuration record buffer
 */
export function MakeAvccConfig(sps: Uint8Array, pps: Uint8Array): Uint8Array {
    // AVCC Configuration Record structure:
    // - configurationVersion (1 byte): always 1
    // - AVCProfileIndication (1 byte): from SPS[1]
    // - profile_compatibility (1 byte): from SPS[2]
    // - AVCLevelIndication (1 byte): from SPS[3]
    // - lengthSizeMinusOne (1 byte): 0xFF (length field is 4 bytes)
    // - numOfSequenceParameterSets (1 byte): 0xE1 (0xE0 | 1)
    // - sequenceParameterSetLength (2 bytes): SPS length
    // - sequenceParameterSetNALUnit (variable): SPS data
    // - numOfPictureParameterSets (1 byte): 1
    // - pictureParameterSetLength (2 bytes): PPS length
    // - pictureParameterSetNALUnit (variable): PPS data
    
    const configLength = 11 + sps.length + pps.length;
    const config = new Uint8Array(configLength);
    
    let offset = 0;
    
    // Configuration version
    config[offset++] = 0x01;
    
    // Profile indication, profile compatibility, level indication (from SPS)
    config[offset++] = sps[1]; // AVCProfileIndication
    config[offset++] = sps[2]; // profile_compatibility
    config[offset++] = sps[3]; // AVCLevelIndication
    
    // Length size minus one (0xFF means 4 bytes length field)
    config[offset++] = 0xFF;
    
    // Number of SPS (0xE1 = 0b11100001, reserved bits + 1 SPS)
    config[offset++] = 0xE1;
    
    // SPS length (big-endian)
    config[offset++] = (sps.length >> 8) & 0xFF;
    config[offset++] = sps.length & 0xFF;
    
    // SPS data
    config.set(sps, offset);
    offset += sps.length;
    
    // Number of PPS
    config[offset++] = 0x01;
    
    // PPS length (big-endian)
    config[offset++] = (pps.length >> 8) & 0xFF;
    config[offset++] = pps.length & 0xFF;
    
    // PPS data
    config.set(pps, offset);
    
    return config;
}
